package com.dong.algorithm.novice.bitoperation;

/**
 * 算法：打印int数的32位
 *
 * @author by jiweidong on 2021/11/15.
 */
public class Alg01_PrintIntNum32Bit {

    public static void printIntNum32Bit(int num) {
        for (int i = 31; i >= 0; i--) {
            System.out.print((num & (1 << i)) == 0 ? "0" : "1");
        }
        System.out.println();
    }

    public static void main(String[] args) {

        int num = 234234232;

        System.out.println("============打印int数的32位");
        printIntNum32Bit(num);

        System.out.println("============解释左移运算符");

        // 解释左移运算符
        printIntNum32Bit(1);
        printIntNum32Bit(1 << 1);
        printIntNum32Bit(1 << 2);
        printIntNum32Bit(1 << 4);
        printIntNum32Bit(1 << 8);
        System.out.println("======");
        printIntNum32Bit(num << 1);
        printIntNum32Bit(num << 2);
        printIntNum32Bit(num << 4);
        printIntNum32Bit(num << 8);
        System.out.println("======");
        // 左移1位就是他的十进制数乘2，左移2位乘4，左移3位乘8，左移n位乘2的n次方（所以左移都是在右侧补0即可）
        System.out.println(1 << 1);
        System.out.println(1 << 2);
        System.out.println(1 << 4);

        System.out.println("============解释补码反码");

        // 解释补码反码
        printIntNum32Bit(Integer.MAX_VALUE);
        printIntNum32Bit(Integer.MIN_VALUE);
        // 在java中，int型中的数字部分实际占31位，最高位是符号位（0表示非负数，1表示负数），所以int型的最大最小范围是 -2的31次幂~2的31次幂-1；
        // （为什么非负数的最大值要减一，因为有0的存在，0算在非负数领域，也要占一个数，所以非负数的最大值只能到2的31次幂-1）
        // （java中只有有符号数，没有无符号数；而C++中是有无符号数的）

        System.out.println("============负数的数字值是对数字部分取反然后加1");

        // 负数的数字值是对数字部分取反然后加1（即下面的求一个数的相反数：取反加一即可；其实和下面重复了。。）
        printIntNum32Bit(-1);
        printIntNum32Bit(~-1);
        System.out.println("======");
        printIntNum32Bit(Integer.MAX_VALUE);
        printIntNum32Bit(Integer.MIN_VALUE);
        printIntNum32Bit(~Integer.MIN_VALUE);
        System.out.println(Integer.MAX_VALUE);
        System.out.println(Integer.MIN_VALUE);
        System.out.println(~Integer.MIN_VALUE);

        System.out.println("============熟悉 与 或 异或 运算符");

        // 熟悉 与 或 异或 运算符
        int a = 1231499;
        int b = 90873452;
        printIntNum32Bit(a);
        printIntNum32Bit(b);
        printIntNum32Bit(a & b);
        printIntNum32Bit(a | b);
        printIntNum32Bit(a ^ b);

        System.out.println("============右移");

        // 右移
        int m = 1024;
        printIntNum32Bit(m);
        printIntNum32Bit(m >> 1);
        printIntNum32Bit(m >>> 1);
        System.out.println("======");
        // >> 表示带符号右移，最左位用符号补上
        // >>> 表示不带符号右移，最左位用0补上
        printIntNum32Bit(Integer.MIN_VALUE);
        printIntNum32Bit(Integer.MIN_VALUE >> 1);
        printIntNum32Bit(Integer.MIN_VALUE >>> 1);
        // 所以对于正数 >> 和 >>> 一样；对于负数 >> 和 >>> 会不一样；

        System.out.println("============用位运算，求一个数的相反数：取反加一即可");

        // 用位运算，求一个数的相反数：取反加一即可
        int x = 5;
        int y = -x;
        int z = ~x + 1;
        System.out.println(x);
        System.out.println(y);
        System.out.println(z);
        printIntNum32Bit(x);
        printIntNum32Bit(y);
        printIntNum32Bit(z);
        // 最小负数的相反数还是它自己
        printIntNum32Bit(Integer.MIN_VALUE);
        printIntNum32Bit(-Integer.MIN_VALUE);
        // 0的相反数还是它自己，
        printIntNum32Bit(0);
        printIntNum32Bit(-0);
    }
}
